package com.bingxue.edu.management.education.service;

import cn.hutool.core.collection.CollectionUtil;
import com.bingxue.edu.common.util.EduUtil;
import com.bingxue.edu.management.education.model.entity.ClassInfo;
import com.bingxue.edu.management.education.model.entity.Enrollment;
import com.mybatisflex.core.util.UpdateEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.bingxue.edu.management.education.model.entity.table.ClassInfoTableDef.CLASS_INFO;
import static com.bingxue.edu.management.education.model.entity.table.EnrollmentTableDef.ENROLLMENT;

/**
 * 续报业务逻辑
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EnrollRenewalService {

    private final EnrollmentService enrollmentService;
    private final ClassInfoService classInfoService;

    /**
     * 报名成功后，设置报名信息续报状态
     * @param currentEnrollment 当前学期报名信息
     * @param currentClassInfo 当前班级
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRenewalStatus(Enrollment currentEnrollment, ClassInfo currentClassInfo) {
        // 查询前序班级报名记录，给每个前序班级设置续报状态
        List<Enrollment> prevEnrollmentList = enrollmentService.queryChain()
                .from(ENROLLMENT)
                .leftJoin(CLASS_INFO).on(CLASS_INFO.ID.eq(ENROLLMENT.CLASS_ID))
                .where(ENROLLMENT.STUDENT_ID.eq(currentEnrollment.getStudentId()))
                .and(ENROLLMENT.CANCEL_LESSON_COUNT.lt(ENROLLMENT.ENROLL_LESSON_COUNT))
                .and(CLASS_INFO.CLASS_YEAR.eq(EduUtil.getPrevClassYear(currentClassInfo)))
                .and(CLASS_INFO.TERM.eq(EduUtil.getPrevClassTerm(currentClassInfo)))
                .and(CLASS_INFO.SUBJECT.eq(currentClassInfo.getSubject()))
                .list();

        for (Enrollment prevEnrollment : prevEnrollmentList) {
            List<String> renewalClassIds = prevEnrollment.getRenewalClassIds() == null ? new ArrayList<>() : prevEnrollment.getRenewalClassIds();
            if (!renewalClassIds.contains(currentClassInfo.getId())) {
                renewalClassIds.add(currentClassInfo.getId());
                updateRenewalClassIds(prevEnrollment, renewalClassIds);
            }
        }
        // 查询后续班级报名记录，给当前班级设置续报班级为后续班级列表
        List<Enrollment> nextEnrollmentList = enrollmentService.queryChain()
                .select(ENROLLMENT.ALL_COLUMNS)
                .from(ENROLLMENT)
                .leftJoin(CLASS_INFO).on(CLASS_INFO.ID.eq(ENROLLMENT.CLASS_ID))
                .where(ENROLLMENT.STUDENT_ID.eq(currentEnrollment.getStudentId()))
                .and(ENROLLMENT.CANCEL_LESSON_COUNT.lt(ENROLLMENT.ENROLL_LESSON_COUNT))
                .and(CLASS_INFO.CLASS_YEAR.eq(EduUtil.getNextClassYear(currentClassInfo)))
                .and(CLASS_INFO.TERM.eq(EduUtil.getNextClassTerm(currentClassInfo)))
                .and(CLASS_INFO.SUBJECT.eq(currentClassInfo.getSubject()))
                .list();
        List<String> renewalClassIds = currentEnrollment.getRenewalClassIds() == null ? new ArrayList<>() : currentEnrollment.getRenewalClassIds();
        for (Enrollment nextEnrollment : nextEnrollmentList) {
            if (!renewalClassIds.contains(nextEnrollment.getClassId())) {
                renewalClassIds.add(nextEnrollment.getClassId());
            }
        }
        updateRenewalClassIds(currentEnrollment, renewalClassIds);
    }

    /**
     * 退班后，取消续报状态
     * @param currentEnrollment 当前学期报名信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancelRenewalStatus(Enrollment currentEnrollment) {
        ClassInfo currentClassInfo = classInfoService.getById(currentEnrollment.getClassId());
        // 查询前序班级报名记录，给每个前序班级取消续报状态
        List<Enrollment> prevEnrollmentList = enrollmentService.queryChain()
                .from(ENROLLMENT)
                .leftJoin(CLASS_INFO).on(CLASS_INFO.ID.eq(ENROLLMENT.CLASS_ID))
                .where(ENROLLMENT.STUDENT_ID.eq(currentEnrollment.getStudentId()))
                .and(CLASS_INFO.CLASS_YEAR.eq(EduUtil.getPrevClassYear(currentClassInfo)))
                .and(CLASS_INFO.TERM.eq(EduUtil.getPrevClassTerm(currentClassInfo)))
                .and(CLASS_INFO.SUBJECT.eq(currentClassInfo.getSubject()))
                .list();

        for (Enrollment prevEnrollment : prevEnrollmentList) {
            List<String> renewalClassIds = prevEnrollment.getRenewalClassIds();
            if (renewalClassIds == null) {
                continue;
            }
            if (renewalClassIds.contains(currentClassInfo.getId())) {
                renewalClassIds.remove(currentClassInfo.getId());
                updateRenewalClassIds(prevEnrollment, renewalClassIds);
            }
        }

        // 给当前报名信息取消续报
        updateRenewalClassIds(currentEnrollment, null);
    }

    private void updateRenewalClassIds(Enrollment enrollment, List<String> renewalClassIds) {
        Enrollment updateEnrollment = UpdateEntity.of(Enrollment.class, enrollment.getId());
        updateEnrollment.setRenewalClassIds(CollectionUtil.isEmpty(renewalClassIds) ? null: renewalClassIds);
        enrollmentService.getMapper().update(updateEnrollment);
    }
}
